#ifndef _MYELF_H_32_64_
#define _MYELF_H_32_64_
/*
 *   this file support all CLASS32 or CLASS64 file system elf parser
 */
#include <elf.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <string.h>

#define FLAGS_ZEROPAD (1U << 0U)
#define FLAGS_LEFT (1U << 1U)
#define FLAGS_PLUS (1U << 2U)
#define FLAGS_SPACE (1U << 3U)
#define FLAGS_HASH (1U << 4U)
#define FLAGS_UPPERCASE (1U << 5U)
#define FLAGS_CHAR (1U << 6U)
#define FLAGS_SHORT (1U << 7U)
#define FLAGS_LONG (1U << 8U)
#define FLAGS_LONG_LONG (1U << 9U)
#define FLAGS_PRECISION (1U << 10U)
#define FLAGS_ADAPT_EXP (1U << 11U)

#ifndef PRINTF_NTOA_BUFFER_SIZE
#define PRINTF_NTOA_BUFFER_SIZE 32U
#endif

#define SUCCESS (1)
#define FAILE (0)

typedef enum order_type
{
    ERROR_ORDER = 0,
    LITTLE_ORDER,
    BIG_ORDER
} order_type_e;

typedef enum bool
{
    false = 0,
    true
} bool;
/*personal definition of elf head */
typedef struct elf_ident
{
    uint8_t elfMagic[4]; /*elf head check magic number*/
    uint8_t classType;   /*elf file check  class32 or class 64 file system*/
    uint8_t dataOreder;  /*elf file bigendian ot little, decide change byte order or not*/
    uint8_t version;
    uint8_t osAbi;
    uint8_t osAbiVersion;
    uint8_t padding[6];
    uint8_t numIdent;
} elf_ident_t;

typedef struct rodata_info64
{
    uint64_t size;   // 数据长度
    uint64_t offset; // 从文件开始位置偏移
    uint64_t addr;   // 开始的虚拟地址
    char *buf;       // 数据部分,需要进行free
} rodata_info64_t;

typedef struct rodata_info32
{
    uint32_t size;   // 数据长度
    uint32_t offset; // 从文件开始位置偏移
    uint32_t addr;   // 开始的虚拟地址
    char *buf;       // 数据部分,需要进行free
} rodata_info32_t;

typedef struct rodata_info
{
    int class_type;
    int change_order;
    rodata_info32_t *rodata_32;
    rodata_info64_t *rodata_64;
} rodata_info_t;

typedef struct buff_header
{
    unsigned int element_num;
    unsigned int len;
} __attribute__((packed)) buff_header_t;

typedef void (*out_fct_type)(char character, void *buffer, size_t idx, size_t maxlen);

int open_elf_file(const char *filename);
int read_elf_ident_header(int fd, elf_ident_t *ident);
rodata_info32_t *parser_elf_class32_ehdr(int fd, Elf32_Ehdr *elf32_ehdr, int change_order_flag);
rodata_info64_t *parser_elf_class64_ehdr(int fd, Elf64_Ehdr *elf64_ehdr, int change_order_flag);
rodata_info_t *load_elf_file(const char *filename);
void free_elf_resource(rodata_info_t *info_p);

char *buf2str_addr32(rodata_info_t *rodata, uint32_t addr, uint32_t str_max_len);                          // 根据输入的在rodata段中的地址返回字符串
char *buf2str_addr64(rodata_info_t *rodata, uint64_t addr, uint32_t str_max_len);                          // 根据输入的在rodata段中的地址返回字符串
char *element2char_p(char **p_data, rodata_info_t *p_rodata_info);                                         // 根据输入的在rodata段中的地址返回字符串,给buf2str_bitStream使用，单独使用时功能同上面两个函数
char *location_string_relocatio_offset(rodata_info_t *rodata, const char *pattern);                        // 根据定位字符串重新定位起始位置
int buf2str_bitStream(rodata_info_t *p_rodata_info, char *buf_out, int out_len, char *buf_in, int in_len); // 将new_sprinf函数转换的数据解析出来
#endif
